// file:include/os/driver.h
// autor:jiangxinpeng
// time:2021.3.12
// copyright:(C) by jiangxinpeng,All right are reserved.

#ifndef OS_DRIVER_H
#define OS_DRIVER_H

#include <os/mdl.h>
#include <os/mutexlock.h>
#include <os/spinlock.h>
#include <os/fsal.h>
#include <os/waitqueue.h>
#include <os/debug.h>
#include <lib/list.h>
#include <lib/type.h>
#include <lib/string.h>
#include <arch/atomic.h>
#include <sys/res.h>
#include <sys/input.h>

#define DISKOFF_MAX ((uint32_t)(~(0)))

// devfs mount path
#define DEVFS_PATH "/dev"

// device name len
#define DRIVER_NAME_LEN 32
// device io status
#define IO_SUCCESS (1 << 0)    // successful
#define IO_FAILED (1 << 1)     // faild
#define IO_PENDiNG (1 << 2)    // pending
#define IO_NOWAITTING (1 << 3) // no waitting
#define IO_KERNEL (1 << 4)     // kernel io

// device max open number
#define DEVICE_NUM_MAX 32

#define IS_BAD_DEVICE_HANDLE(handle) ((handle) < 0 || (handle) > DEVICE_NUM_MAX)
#define GET_DEVICE_BY_HANDLE(handle) (device_handle_table[handle])

// device ioreq function max
#define IOREQ_FUN_MAX 9

// event buffer
#define EVENT_BUFF_SIZE 80

// device dispatch failed
#define DEVICE_DISPATCH_FAILED()                                       \
        {                                                              \
                KPrint(PRINT_ERR "%s: do dispatch faild\n", __func__); \
        }

// device queue entry number
#define DEVICE_QUEUE_ENTRY_NUM 12

// driver iostatus
typedef uint32_t iostatus_t;
// device handle
typedef uint32_t device_handle_t;

// devfs fsal
extern fsal_t devfs_fsal;

// first defined
typedef struct device_object device_object_t;
typedef struct driver_object driver_object_t;

// io require funtion
typedef enum _io_require_flags
{
        IOREQ_OPEN_OPERATOR = 0x01,   // device open
        IOREQ_CLOSE_OPERATOR = 0x02,  // device close
        IOREQ_READ_OPERATOR = 0x04,   // device read
        IOREQ_WRITE_OPERATOR = 0x08,  // device write
        IOREQ_DEVCTL_OPERATOR = 0x10, // device control
        IOREQ_MMAP_OPERATOR = 0x20,   // device mem map
        IOREQ_BUFFER_IO = 0x40,       // device buffer io
        IOREQ_COMPLETION = 0x80,      // device io require completion
        IOREQ_NUM_MAX
} io_require_flags_t;

// device object flags
typedef enum _device_object_flags
{
        DEVICE_NEITHER_IO = 0,       // no buffer io and no mem io
        DEVICE_BUFFER_IO = (1 << 0), // buffer io
        DEVICE_DIRECT_IO = (1 << 1), // mem direct io
        DEVICE_DISPENSE = (1 << 2)   // dispense
} device_object_flags_t;

// ioreq function
typedef enum _io_require_function
{
        IOREQ_OPEN,      // device open index
        IOREQ_CLOSE,     // device close index
        IOREQ_READ,      // device read index
        IOREQ_WRITE,     // device write index
        IOREQ_DEVCTL,    // device control index
        IOREQ_MMAP,      // device memory map index
        IOREQ_FASTIO,    // device fast io index
        IOREQ_FASTWRITE, // device fast write index
        IOREQ_FASTREAD,  // device fast read index
        IOREQ_FUNCTION_MAX
} io_require_function_t;

// io parame block
typedef struct io_parame_t
{
        union
        {
                struct
                {
                        uint32_t flags;
                        char *devname;
                } open;
                struct
                {
                        uint32_t len;
                        uint32_t offset;
                } read;
                struct
                {
                        uint32_t len;
                        uint32_t offset;
                } write;
                struct
                {
                        uint32_t code;
                        uint32_t arg;
                } devctl;
                struct
                {
                        uint32_t flags;
                        size_t len;
                } mmap;
        };
} io_parame_t;

// io status block
typedef struct io_status_block_t
{
        iostatus_t status; // io status
        uint64_t info;     // io result information
} io_status_block_t;

// i/o require block
typedef struct io_request_t
{
        uint32_t flags;              // flags
        list_t list;                 // list
        mdl_t *mdl_list;             // mem descript list
        void *sys_buff;              // system buffer
        void *user_buff;             // user buffer
        device_object_t *devobj;     // device object
        io_parame_t parame;          // parame
        io_status_block_t io_status; // io status block
} io_request_t;

// driver dispatch fun
typedef iostatus_t (*driver_dispatch_t)(device_object_t *dev, io_request_t *ioreq);
typedef iostatus_t (*driver_dispatch_fastio_t)(device_object_t *dev, int arg, void *buff);

// driver standard fun
typedef iostatus_t (*driver_fun_t)(driver_object_t *driver);

// device list
typedef struct device_object
{
        list_t list;             // device list
        device_type_t type;      // device type
        driver_object_t *driver; // device driver point
        void *device_extension;  // device extension space point
        uint32_t flags;          // device flags
        atomic_t ref;            // ref count
        io_request_t *cur_ioreq; // current io require
        string_t name;           // device name
        struct                   // device lock
        {
                spinlock_t spinlock;
                mutexlock_t mutexlock;
        } lock;
        uint16_t mtime; // modify time
        uint16_t mdate; // modify date
        uint32_t reserved;
} device_object_t;

// driver object
typedef struct driver_object
{
        uint32_t flags;         // driver flags
        list_t list;            // driver list
        list_t device_list;     // device list
        void *driver_extension; // driver extension;
        string_t name;          // driver name
        // driver control function
        driver_fun_t driver_enter;
        driver_fun_t driver_exit;
        // driver dispatch function
        driver_dispatch_t dispatch_fun[IOREQ_FUN_MAX];
        spinlock_t device_lock; // device lock
} driver_object_t;

// device queue entry
typedef struct
{
        list_t list;   // list
        uint8_t *buff; // buffer
        int length;    // data length
} device_queue_entry_t;

// device queue
typedef struct
{
        list_t list_head;        // queue head
        spinlock_t lock;         // queue lock
        wait_queue_t wait_queue; // wait queue;
        uint32_t count;          // queue tern count
} device_queue_t;

typedef struct _input_even_buff
{
        input_event_t *buff; // event buffer
        uint32_t head, tail;
        spinlock_t lock;
} input_event_buff_t;

typedef struct
{
        devent_t devent;
        devent_t *curptr;
} devfs_dir_extension_t;

typedef struct
{
        device_handle_t handle;
} devfs_file_extension_t;

void DriverFrameInit();
int SysScanDev(devent_t *in, device_type_t type, devent_t *out);

iostatus_t IoCreateDevice(driver_object_t *driver, uint32_t dev_exten_size, char *devname, device_type_t type, device_object_t **device);
int IoDeleteDevice(device_object_t *device);
device_object_t *IoSearchDeviceByName(char *devname);
driver_object_t *IoSearchDriverByName(char *name);
int IoCompleteCheck(io_request_t *ioreq, iostatus_t status);
iostatus_t IoCallDriver(device_object_t *devobj, io_request_t *ioreq);
void IoCompleteRequest(io_request_t *ioreq);

iostatus_t IoDeviceIncRef(device_object_t *devobj);
iostatus_t IoDeviceDecRef(device_object_t *devobj);

iostatus_t DefaultDeviceDispatch(device_object_t *devobj, io_request_t *ioreq);

io_request_t *IoRequireAlloc();
void IoRequireFree(io_request_t *ioreq);

void DriverObjectInit(driver_object_t *driver);
int DriverObjectCreate(driver_fun_t fun);
int DriverObjectDel(driver_object_t *driver);

int DeviceHandleTableInsert(device_object_t *devobj);
int DeviceHandleTableRemove(device_object_t *devobj);
device_object_t *DeviceHandleTableFindByName(char *devname);
int DeviceHandleTableFindByObject(device_object_t *device);

device_handle_t DeviceOpen(char *dev, int flags);
int DeviceClose(device_handle_t handle);
int DeviceIncRef(int handle);
int DeviceDecRef(int handle);
int DeviceRead(device_handle_t handle, void *buff, size_t size, offset_t off);
int DeviceWrite(device_handle_t handle, void *buff, size_t size, offset_t off);
int DeviceDevCtl(device_handle_t handle, int cmd, void *arg);
void *DeviceMMap(device_handle_t handle, size_t len, int flags);
int DeviceProbeUnUsed(const char *name, char *buff, size_t len);
int FastIoCall(device_handle_t handle,int arg,void *buff,int dispatch);


int InputEventInit(input_event_buff_t *event_buff);
int InputEventPut(input_event_buff_t *event_buff, input_event_t *event);
int InputEventGet(input_event_buff_t *event_buff, input_event_t *event);
int InputEventFull(input_event_buff_t *event_buff);
int InputEventEmpty(input_event_buff_t *event_buff);

void IoDeviceQueueCleanup(device_queue_t *queue);
void IoDeviceQueueInit(device_queue_t *queue);
iostatus_t IoDeviceQueueAppend(device_queue_t *queue, uint8_t *buff, int len);
int IoDeviceQueuePickup(device_queue_t *queue, uint8_t *buff, uint32_t bufflen, int flags);

void DriverFrameDump();

#endif